var Xmpp = 
{
    connection: null,
    
    /*  TODO: this supports only single subscriber at a time, need to make this into an array to
     *  support multiple subscription requests */
    pending_subscriber: null, 
    
    show_values: ["offline", "xa", "away", "dnd", "chat"],
    
    connect : function()
    {
       log("Xmpp.connect: starting");
       
       var username = Ui.getUserJid();
       var password = Ui.getUserPassword();

       log("Connecting ", username, " with password ", password);

       var connection = new Strophe.Connection("http://bosh.metajack.im:5280/xmpp-httpbind");
       connection.connect(username, password, Xmpp.on_connection_status_changed);      
       Xmpp.connection = connection;
       
       log("Xmpp.connect: exiting");
    },
    
    disconnect : function()
    {
       log("Xmpp.disconnect: starting"); 
       
       Xmpp.connection.disconnect();
       Xmpp.connection = null;
       Ui.removeAllContacts();
       
       log("Xmpp.disconnect: exiting"); 
    },
    
    get_roster : function()
    {
        log("Xmpp.get_roster: starting"); 
        
        var iq = $iq({type: 'get'}).c('query', {xmlns: 'jabber:iq:roster'});
        Xmpp.connection.sendIQ(iq, Xmpp.on_roster_get);
        
        log("Xmpp.get_roster: exiting"); 
    },

    on_roster_get : function(iq)
    {
        log("Xmpp.on_roster_get: starting"); 
        log(iq);
        
        $(iq).find('item').each
        (
            function()
            {
                var jid = $(this).attr('jid');
                var name = $(this).attr('name') || jid;
                var subscription = $(this).attr('subscription'); 
                var show = Xmpp.show_values[0];
                var status = "";
                if ($(this).attr('ask') === "subscribe" || (subscription === "none"))
                {
                    /* TODO: need to check the spec on this case */
                    status = "Awaiting authorization";
                }
                else if (subscription === 'from')
                {
                    status = "follower";
                }
                Ui.insertContact(jid, name, show, status);
                
            }
        );

        // Set up presence handler.
        Xmpp.connection.addHandler(Xmpp.on_presence_changed, null, "presence");
        
        // Send initial presence.
        Xmpp.connection.send($pres());
        
        log("Xmpp.on_roster_get: exiting"); 
    },

    on_roster_changed : function(iq)
    {
        log("Xmpp.on_roster_changed: starting");
        log(iq);
        
        $(iq).find("item").each
        (
            function()
            {
                var subscription        = $(this).attr("subscription");
                var jid                 = $(this).attr("jid");
                var name                = $(this).attr("name") || jid;

                log("on_roster_changed : " + " subscription_value: " + subscription + " jid: " + jid + " name: " + name);
                
                if (subscription === "remove")
                {
                    Ui.removeContact(jid);
                }
                else
                {
                    if (Ui.isContact(jid))
                    {
                        Ui.replaceContact(jid, name);
                    }
                    else
                    {
                        var show = Xmpp.show_values[0];
                        
                        var status = "";
                        if ($(this).attr('ask') === "subscribe" || (subscription === "none"))
                        {
                            /* TODO: need to check the spec on this case */
                            status = "Awaiting authorization";
                        }
                        else if (subscription === 'from')
                        {
                            status = "follower";
                        }
                        
                        Ui.insertContact(jid, name, show, status);
                    }
                }
            }
        );
            
        log("Xmpp.on_roster_changed: exiting");    
        // This handler should be kept attached to this event.    
        return true;  
    },
    
    on_presence_changed: function (presence)
    {
        log("Xmpp.on_presence_changed: starting");
        log(presence);
        
        var ptype = $(presence).attr('type');
        var from = $(presence).attr('from');

        log("on_presence_changed : " + "ptype: " + ptype + " from: " + from + " show: " + $(presence).find("show").text());

        if (ptype === "subscribe")
        {
            Xmpp.pending_subscriber = from;
            var requesterJid = Strophe.getBareJidFromJid(from);
            Ui.showPresenceRequestApprovalDialog(requesterJid);
        }
        else if (ptype !== "error") 
        {
            var show    = (ptype === "unavailable") ? Xmpp.show_values[0] : $(presence).find("show").text();
            if (show === "")
                show = "chat";
            
            var status  = $(presence).find("status").text();
            
            Ui.setContactPresenceShow(from, show);
            Ui.setContactPresenceStatus(from, status);
       }

       if (ptype !== "error")
       {
            Ui.setChatTabData(from);
       }

       log("Xmpp.on_presence_changed: exiting");
       return true;
    },
    
    on_message_get: function(message)
    {
        log("Xmpp.on_message_get: starting");
        log(message);
        
        var full_jid = $(message).attr("from");
        var jid = Strophe.getBareJidFromJid(full_jid);
        if (Ui.isChattingWith(jid) === false)
        {
            var name = Ui.getContactName(jid);
            if (name === "")
                name = jid;
            Ui.createChatTab(full_jid, name);
        }
        
        Ui.selectChatTab(jid);
        Ui.setChatTabData(full_jid);
       
        var isDelayedMessage = $(message).find('delay').length > 0 ? true : false ;
        var body = $(message).find("html > body");
        if (body.length === 0)
        {
            body = $(message).find("body");
            body =  (body.length > 0) ? body.text() : null;
        }
        else
        {
            body = body.contents();            
            var span = $("<span></span>");
            
            body.each
            (
                function()
                {
                    if (document.importNode)
                    {
                        $(document.importNode(this, true)).appendTo(span);
                    }
                    else
                    {
                        // IE workaround
                        span.append(this.xml);
                    }
                }
            );
                
            body = span.text();
        }
        
        if (body)
        {
            Ui.appendChatMessage(false, jid, body, isDelayedMessage);
            Ui.scrollChat(jid); 
        }
        
        log("Xmpp.on_message_get: exiting");
        return true;
    },

    add_contact : function(user_data)
    {
        log("Xmpp.add_contact: starting");
        
        var iq = $iq({type: "set"}).c("query", {xmlns: "jabber:iq:roster"}).c("item", user_data);
        Xmpp.connection.sendIQ(iq);

        var subscribe = $pres({to: user_data.jid, type: "subscribe"});
        Xmpp.connection.send(subscribe);
        
        log("Xmpp.add_contact: exiting");
    },

    on_connection_status_changed : function(status)
    {
        var connected = false;
        log("connection_status: " + status.toString());
        
        if (status === Strophe.Status.CONNECTING)
        {
           $('#connection_create').showLoading();            
           log("CONNECTING to jabber server");
        }
        else if (status === Strophe.Status.AUTHENTICATING)
        {
           $('#connection_create').showLoading();            
           log("AUTHENTICATING to jabber server");
        }        
        if (status === Strophe.Status.CONNECTED)
        {
           connected = true; 
           $('#connection_create').hideLoading(); 
           log("CONNECTED to jabber server");
           
           Ui.showContacts();
           Xmpp.get_roster();
           Xmpp.connection.addHandler(Xmpp.on_roster_changed, "jabber:iq:roster", "iq", "set");
           Xmpp.connection.addHandler(Xmpp.on_message_get, null, "message", "chat");
        }      
        else if (status === Strophe.Status.DISCONNECTING)
        {
           $('#connection_create').showLoading();            
           log("DISCONNECTING from jabber server");
        }        
        else if (status === Strophe.Status.DISCONNECTED)
        {
           $('#connection_create').hideLoading();  
           log("DISCONNECTED from jabber server");
        }
        else if (status === Strophe.Status.CONNFAIL)
        {
           $('#connection_create').hideLoading();  
           log("CONNFAIL to jabber server");
        }
        else if (status === Strophe.Status.AUTHFAIL)
        {
           $('#connection_create').hideLoading();  
           log("AUTHFAIL to jabber server");
        }
        
        if (connected)
        {
           $("#connection_create").addClass("hidden");
           $("#connection_destroy").removeClass("hidden");
        }
        else
        {
           $("#connection_create").removeClass("hidden");
           $("#connection_destroy").addClass("hidden");            
        }
    }    
};
